#!/usr/bin/env python
#
# group_menu.py
#
# Version : 0.7
# Date : 20080520
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

# group_menu.py - Displays group menu panel and is a module in sm_gui
# package, run as part of the skipolemonitor gui interface
#
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

""" This is a module in the sm_gui package, and defines the Group menu panel

It is run as part of the skipolemonitor gui interface.
"""


import wx
import makehtml
from net import *


class Group(wx.Panel):
    """The Group menu, shown in the right panel when a group is selected."""
    def __init__(self, parent, sp):
        wx.Panel.__init__(self, parent)
        # sp is the splitter window holding this group
        self.item = 1
        self.sp = sp
        #
        # Create the sizer for this panel
        self.menu_sizer=wx.BoxSizer(wx.VERTICAL)
        #
        # Create FlexGridSizer for the text entry fields
        #
        self.group_fields_sizer=wx.FlexGridSizer(rows=0, cols=2, hgap=5, vgap=5)
        #
        # Short name text control
        # Label
        self.group_shortname_label=wx.StaticText(self, -1, "Short Name: ")
        self.group_fields_sizer.Add(self.group_shortname_label,
                                    0,
                                    wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                    20)
        # Field
        self.group_shortname_field = wx.TextCtrl(self, -1, get_net(self.item, NAME))
        self.group_shortname_field.SetMinSize((150,-1))
        self.group_shortname_field.SetToolTipString("Group name, maximum\n12 characters.")
        self.group_fields_sizer.Add(self.group_shortname_field,
                                    0,
                                    wx.TOP | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
                                    20)
        #
        # Description text control
        # Label
        self.group_description_label=wx.StaticText(self, -1, "Description: ")
        self.group_fields_sizer.Add(self.group_description_label,
                                    0,
                                    wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                    20)
        # Field
        self.group_description_field = wx.TextCtrl(self, -1, get_net(self.item, DESCRIPTION))
        self.group_description_field.SetMinSize((150,-1))
        self.group_fields_sizer.Add(self.group_description_field,
                                    0,
                                    wx.TOP | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.EXPAND,
                                    20)
        #
        # Email Alert Enabled
        # Label
        self.group_email_label=wx.StaticText(self, -1, "Enable Email Alert: ")
        self.group_fields_sizer.Add(self.group_email_label, 0, wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT, 20)
        # Field
        self.group_email_field = wx.CheckBox(self, -1, "Send email if this group changes status")
        self.group_fields_sizer.Add(self.group_email_field,
                                    0,
                                    wx.TOP | wx.RIGHT | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
                                    20)
        if get_net(self.item, EMAIL):
            self.group_email_field.SetValue(1)
        else:
            self.group_email_field.SetValue(0)
        #
        # Make column 1 growable - this allows the right hand description field to grow
        self.group_fields_sizer.AddGrowableCol(1,0)
        #
        # And nest the FlexGridSizer as the first row of the menu_sizer
        self.menu_sizer.Add(self.group_fields_sizer, 0, wx.EXPAND)
        #
        # Buttons
        #
        button_size = (150,30)
        #
        # Apply button
        self.group_apply_button = wx.Button(self, label="Apply", size=button_size)
        self.group_apply_button.Enable(False)
        self.group_apply_button.SetToolTipString("Click to apply changes.")
        self.menu_sizer.Add(self.group_apply_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Add a sub group button
        self.add_subgroup_button = wx.Button(self, label="Add a sub group", size=button_size)
        self.menu_sizer.Add(self.add_subgroup_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Add a host button
        self.add_host_button = wx.Button(self, label="Add a host", size=button_size)
        self.menu_sizer.Add(self.add_host_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Delete this group button
        self.delete_group_button = wx.Button(self, label="Delete this group", size=button_size)
        self.delete_group_button.SetToolTipString("Delete Group, only if it has no contents.")
        # If this is the top group, the delete button must be disabled
        if self.item == 1:
            self.delete_group_button.Enable(False)
        else:
            # Check if this item has any contents, if it has, the delete button must be disabled
            for id in network(self.item):
                # Check if the device has this item for a parent
                if get_net(id, PARENT) ==  self.item :
                    # A child has been found, disable the button
                    self.delete_group_button.Enable(False)
                    break
        self.menu_sizer.Add(self.delete_group_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Set the size to the panel
        self.SetSizer(self.menu_sizer)
        #
        # Create bindings
        self.Bind(wx.EVT_TEXT, self.group_shortname, self.group_shortname_field)
        self.Bind(wx.EVT_TEXT, self.group_description, self.group_description_field)
        self.Bind(wx.EVT_CHECKBOX, self.group_email, self.group_email_field)
        self.Bind(wx.EVT_BUTTON, self.group_apply, self.group_apply_button)
        self.Bind(wx.EVT_BUTTON, self.add_subgroup, self.add_subgroup_button)
        self.Bind(wx.EVT_BUTTON, self.add_host, self.add_host_button)
        self.Bind(wx.EVT_BUTTON, self.delete_group, self.delete_group_button)


    def set_item(self, item):
        """Set the item for this group menu"""
        if not is_net_exists(item): return
        if is_net_host(item): return
        #
        self.item = item
        #
        self.group_shortname_field.SetValue(get_net(self.item, NAME))
        #
        self.group_description_field.SetValue(get_net(self.item, DESCRIPTION))
        #
        if get_net(self.item, EMAIL):
            self.group_email_field.SetValue(1)
        else:
            self.group_email_field.SetValue(0)
        #
        # Normally, if just selected, the apply button will be disabled
        self.group_apply_button.Enable(False)
        #
        # Should the delete button be enabled or disabled ?
        # If this is the top group, the delete button must be disabled
        if self.item == 1:
            self.delete_group_button.Enable(False)
        else:
            self.delete_group_button.Enable(True)
            # Check if this item has any contents, if it has, the delete button must be disabled
            for id in network(self.item):
                # Check if the device has this item for a parent
                if get_net(id, PARENT) ==  self.item :
                    # A child has been found, disable the button
                    self.delete_group_button.Enable(False)
                    break

    
    # Group fields edited, limit their length, and enable
    # the Apply button

    def group_shortname(self, event):
        """Group short name menu item"""
        # Limit user input to 12 characters
        self.group_apply_button.Enable(True)
        text = event.GetString()
        if len(text)>12:
            pos=self.group_shortname_field.GetInsertionPoint()
            self.group_shortname_field.Remove(12,len(text)+1)
            self.group_shortname_field.SetInsertionPoint(pos)

    def group_description(self, event):
        """Group description menu item"""
        # Limit user input to 80 characters
        self.group_apply_button.Enable(True)
        text = event.GetString()
        if len(text)>80:
            pos=self.group_description_field.GetInsertionPoint()
            self.group_description_field.Remove(80,len(text)+1)
            self.group_description_field.SetInsertionPoint(pos)

    def group_email(self, event):
        """Group Email checkbox toggled"""
        self.group_apply_button.Enable(True)
        return


    # Group Menu Apply button pressed

    def group_apply(self, event):
        """ Apply button - group short name and description"""
        # disable the Apply button
        self.group_apply_button.Enable(False)
        #
        # Short Name
        text=self.group_shortname_field.GetValue()
        text=str(text).strip()
        #
        # apply Short Name to the tree
        tree_item = self.sp.tree.GetSelection()
        self.sp.tree.SetItemText(tree_item, text)
        #
        # apply to the network item
        set_net(self.item, NAME, text)
        #
        # Description
        text=self.group_description_field.GetValue()
        text=str(text).strip()
        # apply description to the network item
        set_net(self.item, DESCRIPTION, text)
        #
        # Email alerts
        if self.group_email_field.GetValue():
            set_net(self.item, EMAIL, 1)
        else:
            set_net(self.item, EMAIL, 0)
        #
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Flag the html pages need refreshing
        set_flag_html_refresh()

    def add_subgroup(self, event):
        """Add a sub group with default short name and description"""
        #
        # get tree item currently selected
        tree_item = self.sp.tree.GetSelection()
        #
        # New Tree Item
        # Note : use AppendItem rather than PrependItem, so this puts a group at the
        # end of the child items, (hosts get added to the beginning)
        new_tree_item=self.sp.tree.AppendItem(tree_item, "New Group", data=None)
        new_network_item=last_net()+1
        self.sp.tree_dev[new_network_item]=new_tree_item
        self.sp.tree.SetItemPyData(new_tree_item, new_network_item)
        self.sp.tree.SetItemBold(new_tree_item, bold=True)
        self.sp.tree.SetItemImage(new_tree_item, self.sp.il_whitegroup, wx.TreeItemIcon_Normal)
        #
        # apply to the network
        add_net_item(new_network_item, [self.item,"0",0,"New Group","New Group description",0,0,0,"0"])
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        #
        # Select the new group
        self.sp.tree.SelectItem(new_tree_item)

    def add_host(self, event):
        """Add a host with default short name, description and ip address"""
        #
        # get tree item currently selected
        tree_item = self.sp.tree.GetSelection()
        #
        # New Tree Item
        # Note : use PrependItem rather than AppendItem, so this puts a host at the
        # beginning of the child items, (groups get added to the end)
        new_tree_item=self.sp.tree.PrependItem(tree_item, "New Host", data=None)
        new_network_item=last_net()+1
        self.sp.tree_dev[new_network_item]=new_tree_item
        self.sp.tree.SetItemPyData(new_tree_item, new_network_item)
        self.sp.tree.SetItemImage(new_tree_item, self.sp.il_white, wx.TreeItemIcon_Normal)
        #
        # apply to the network
        add_net_item(new_network_item, [self.item,"127.0.0.1",0,"New Host","New Host description",0,0,0,"0"])
        #
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Select the new host
        self.sp.tree.SelectItem(new_tree_item)

    def delete_group(self, event):
        """Delete this group"""
        #
        # get tree item currently selected
        tree_item = self.sp.tree.GetSelection()
        #
        # Message Box
        short_name=get_net(self.item, NAME)
        retCode=wx.MessageBox("Are you sure you wish to\ndelete \"%s\"" % short_name,
                              "Delete Group",
                              wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP)
        if retCode != wx.YES : return
        #
        # Delete its html page
        makehtml.del_html_page(self.item)
        #
        # Delete the group
        del_net_item(self.item)
        #
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Request refresh of html pages
        set_flag_html_refresh()
        #
        # Delete from tree
        self.sp.tree.Delete(tree_item)
        # 
        # Having deleted an item, a new item is automatically selected
        #
        tree_item = self.sp.tree.GetSelection()
        # get the dictionary item
        self.item=self.sp.tree.GetItemPyData(tree_item)



